package org.hilo.boot.app.config;

import java.util.LinkedHashMap;
import java.util.List;

import org.hilo.boot.core.UT;
import org.hilo.boot.core.db.DataSourceLookupStrategy;
import org.hilo.boot.core.db.DynamicRoutingDataSource;
import org.hilo.boot.core.db.ExtDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;

/**
 * 动态多数据源配置
 * 
 * @author zollty
 * @since 2018年6月5日
 */
@Configuration
@ConditionalOnProperty(name = "hilo.multi.datasource.names")
public class DruidDataSourceConfig {
    private static final Logger logger = LoggerFactory.getLogger(DruidDataSourceConfig.class);
    
    @Bean("dataSource")
    public DynamicRoutingDataSource dataSource(Environment environment, 
            @Autowired(required = false) List<Filter> filters,
            @Autowired(required = false) DataSourceLookupStrategy lookupKeyStrategy) {
        logger.info("find druid filter 【" + filters + "】");
        Binder binder = Binder.get(environment);

        String dataSourceNames = environment.getProperty("hilo.multi.datasource.names");
        if (UT.Str.isEmpty(dataSourceNames)) {
            dataSourceNames = "default";
        }
        String[] dsArray = UT.Split.split(dataSourceNames, ',');
        LinkedHashMap<Object, ExtDataSource> targetDatasources = new LinkedHashMap<>();
        for (String dataSourceName : dsArray) {
            DruidDataSource ds = binder.bind("hilo.multi.datasource." + dataSourceName, 
                    Bindable.of(DruidDataSource.class)).get();
            ds.setProxyFilters(filters);

            if (ds.getUsername() == null) {
                ds.setUsername(environment.getProperty("spring.datasource.username"));
            }
            if (ds.getPassword() == null) {
                ds.setPassword(environment.getProperty("spring.datasource.password"));
            }
            if (ds.getUrl() == null) {
                ds.setUrl(environment.getProperty("spring.datasource.url"));
            }
            if (ds.getDriverClassName() == null) {
                ds.setDriverClassName(environment.getProperty("spring.datasource.driver-class-name"));
            }
            targetDatasources.put(dataSourceName, buildExtDataSource(ds));
            logger.info("Data source 【" + dataSourceName + "】initialization successfully ...");
        }

        DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();
        dynamicDataSource.setDefaultTargetDataSource(targetDatasources.get(dsArray[0]));
        dynamicDataSource.setTargetDataSources(targetDatasources);
        if (lookupKeyStrategy != null) {
            dynamicDataSource.setLookupKeyStrategy(lookupKeyStrategy);
        }
        dynamicDataSource.afterPropertiesSet();
        return dynamicDataSource;
    }

    private ExtDataSource buildExtDataSource(DruidDataSource ds) {
        ExtDataSource ret = new ExtDataSource(ds);
        ret.setName(ds.getName());
        ret.setUsername(ds.getUsername());
        ret.setPassword(ds.getPassword());
        ret.setUrl(ds.getUrl());
        ret.setDriverClassName(ds.getDriverClassName());
        return ret;
    }
}
